#include <stdio.h>     // printf、perror 等标准输入输出函数
#include <unistd.h>    // pipe、fork、close、write、sleep 等系统调用
#include <string.h>    // strlen，用于字符串长度计算
#include <stdlib.h>    // exit
#include <sys/types.h> // pid_t 类型定义
#include <sys/wait.h>  // waitpid，用于等待子进程退出

// 情况四:读端进程将读端关闭，而写端进程还在一直向管道写入数据，那么操作系统会将写端进程杀掉。

int main()
{
    int fd[2] = {0}; // 创建一个长度为2的文件描述符数组：fd[0] 是读端，fd[1] 是写端

    // 创建匿名管道，fd 数组中保存管道的两个端点
    if (pipe(fd) < 0)
    {
        perror("pipe"); // 如果 pipe 创建失败，输出错误信息
        return 1;       // 非正常退出
    }

    // 创建子进程
    pid_t id = fork();
    if (id == 0)
    {
        // ===== 子进程逻辑 =====

        close(fd[0]); // 子进程关闭管道读端，只写不读

        const char *msg = "hello father, I am child...";
        int count = 10; // 总共发送10次消息
        while (count--)
        {
            write(fd[1], msg, strlen(msg)); // 向管道中写入数据
            sleep(1);                       // 每秒写一次，模拟持续通信
        }

        close(fd[1]); // 写完后关闭写端，表示通信结束
        exit(0);      // 子进程正常退出
    }

    // ===== 父进程逻辑 =====

    close(fd[1]); // 父进程关闭管道写端，因为它只需要读

    close(fd[0]); // 此处也将读端关闭，说明父进程并不打算读取数据（只模拟完整流程）

    int status = 0;
    waitpid(id, &status, 0); // 等待子进程退出，并获取其退出状态

    // 打印子进程的终止信号（如果是信号终止）
    // status & 0x7F 是 POSIX 中提取终止信号的方式
    printf("child get signal:%d\n", status & 0x7F);

    return 0;
}
